﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Migrator.Entities;
using Migrator.Util;
using Migrator.Services.Registration.Packets;
using Migrator.Core;

namespace Migrator.Services.MobileIPNodeService
{
    public class Registerer
    {
        public Registerer(Node sender)
        {
            this.sender = sender;
        }

        public void Register(Node homeAgent, 
            Node foreignAgent, 
            IPAddress careOfAddress, 
            bool usingCoLocatedAddress,
            bool registrationRequired, 
            bool preferReceiveBroadcastPackets, 
            bool preferSimultaneousBindings,
            ushort requestedLifetime)
        {
            RegistrationRequestPacket packet;
            bool useCoLocatedAddress = usingCoLocatedAddress && !registrationRequired;

            // If it's not necessary to register with my foreign agent...
            if (useCoLocatedAddress)
            {
                // TODO: The source address must be the co-located address
                packet = new RegistrationRequestPacket(sender, homeAgent.IPAddress);
            }
            else
            {
                packet = new RegistrationRequestPacket(sender, foreignAgent.IPAddress);
            }

            packet.B = preferReceiveBroadcastPackets;
            packet.CareOfAddress = careOfAddress;
            packet.D = usingCoLocatedAddress;
            packet.HomeAgent = homeAgent.IPAddress;
            packet.Lifetime = requestedLifetime;
            packet.S = preferSimultaneousBindings;

            // Send the packet
            if (useCoLocatedAddress)
            {
                this.sender.Send(packet);
            }
            else
            {
                // Send the packet to the foreign agent
                this.sender.SendLinkLayer(packet, foreignAgent.MACAddress);
            }

            RegistrationsTable.Entry entry = new RegistrationsTable.Entry(
                useCoLocatedAddress ? null : foreignAgent,
                useCoLocatedAddress ? homeAgent.IPAddress : foreignAgent.IPAddress,
                careOfAddress,
                Simulator.Instance.Clock + 10, // Expire after 10 seconds without reply
                requestedLifetime
                );
            pendingRegistrations.Add(entry);
        }

        public RegistrationsTable PendingRegistrations
        {
            get { return this.pendingRegistrations; }
        }

        private Node sender;
        private RegistrationsTable pendingRegistrations = new RegistrationsTable();
    }
}
